package drongo.desktop.tools
{
	import drongo.desktop.tools.events.TraceableEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.OutputProgressEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.utils.ByteArray;
	
	public class FileSave extends EventDispatcher
	{
		public function FileSave()
		{
			
		}
		/**
		 * 保存文件 
		 * @param source													文件/文件夹路径/二进制数据
		 * @param target													存放目录或直接指定存放路径及文件名
		 * @param defaultFileName(注意是带后缀的)			只有source为二进制时,target，source是一个文件夹路径时，作为文件名保存<br>
		 * 注意：当source为二进制数据时，target可以为空（会打开一个窗口让用户自己选择存放在什么地方）
		 */
		public function save(source:Object,target:String=null,defaultFileName:String=null):void{
			var sourceFile:File;
			var targetFile:File
			if(source is ByteArray){
				_saveByByteArray(source as ByteArray,target,defaultFileName);
			}else if(source is String){
				if(target==null){
					this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","souce为文件路径或文件夹时，target参数不能为空！"));
					return;
				}
				sourceFile=new File(source as String);
				if(!sourceFile.exists){
					this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","文件或文件夹:"+source+"不存在！"));
				}else{
					targetFile=new File(target);
					//如果是copy文件夹,而target不是文件夹
					if(sourceFile.isDirectory&&targetFile.extension!=null){
						this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","source为文件夹时target必须是文件夹!"));
					}else{//文件
						if(targetFile.extension==null){//target是文件夹
							targetFile=new File(targetFile.nativePath+File.separator+sourceFile.name);
						}
					}
					sourceFile.copyToAsync(targetFile,true);
					sourceFile.addEventListener(Event.COMPLETE,_copyFileHandler);
					sourceFile.addEventListener(IOErrorEvent.IO_ERROR,_copyFileHandler);
					sourceFile.addEventListener(ProgressEvent.PROGRESS,_copyFileHandler);
				}
			}else{
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","souce参数只能为String/ByteArray"));
			}
		}
		private var _data:ByteArray;
		private function _saveByByteArray(data:ByteArray,target:String=null,defaultFileName:String=null):void{
			var file:File;
			if(target==null){
				file=File.applicationDirectory;
				file.save(data,defaultFileName);
				file.addEventListener(Event.COMPLETE,_fileSaveHandler);
				file.addEventListener(Event.CANCEL,_fileSaveHandler);
				file.addEventListener(ProgressEvent.PROGRESS,_fileSaveHandler);
				file.addEventListener(Event.OPEN,_fileSaveHandler);
			}else{
				this._data=data;
				file=new File(target);
				if(file.extension==null){
					if(defaultFileName==null){
						this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","souce为二进制时，target为文件夹时defaultFileName 不能都为空！"));
						return;
					}
					file=new File(file.nativePath+File.separator+defaultFileName);
				}
				if(file.extension==null){
					this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave","souce为二进制时，target为文件夹，defaultFileName不能不带后缀的文件名"));
					return;
				}
				var fileStream:FileStream=new FileStream();
				fileStream.addEventListener(Event.COMPLETE,_fileStreamOpenFileHandler);
				fileStream.addEventListener(IOErrorEvent.IO_ERROR,_fileStreamOpenFileHandler);
				fileStream.openAsync(file,FileMode.UPDATE);
			}
		}
		private function _fileStreamOpenFileHandler(e:Event):void{
			var fileStream:FileStream=e.target as FileStream;
			fileStream.removeEventListener(Event.COMPLETE,_fileStreamOpenFileHandler);
			fileStream.removeEventListener(IOErrorEvent.IO_ERROR,_fileStreamOpenFileHandler);
			if(e is IOErrorEvent){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave",IOErrorEvent(e).text));
			}else{
				fileStream.position=0;
				fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS,_fileStreamWriteHandler);
				fileStream.addEventListener(Event.CLOSE,_fileStreamWriteHandler);
				fileStream.writeBytes(this._data);
				fileStream.close();
			}
		}
		private function _fileStreamWriteHandler(e:Event):void{
			if(e is OutputProgressEvent){
				var total:Number=OutputProgressEvent(e).bytesTotal;
				var index:Number=total-OutputProgressEvent(e).bytesPending;
				this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"FileSave","FileStreamWrite",index,total));
			}else{
				this.dispatchEvent(new TraceableEvent(TraceableEvent.COMPLETE,"FileSave","FileStreamWrite"));
			}
		}
		private function _copyFileHandler(e:Event):void{
			var file:File=e.target as File;
			file.removeEventListener(Event.COMPLETE,_copyFileHandler);
			file.removeEventListener(IOErrorEvent.IO_ERROR,_copyFileHandler);
			if(e is IOErrorEvent){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.ERROR,"FileSave",IOErrorEvent(e).text));
			}else if(e is ProgressEvent){
				this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"FileSave","copyFile",ProgressEvent(e).bytesLoaded,ProgressEvent(e).bytesTotal));
			}else{
				this.dispatchEvent(new TraceableEvent(TraceableEvent.COMPLETE,"FileSave","copyFile"));
			}
		}
		private function _fileSaveHandler(e:Event):void{
			var file:File=e.target as File;
			var eventType:String=e.type;
			switch(eventType)
			{
				case Event.OPEN:
				case ProgressEvent.PROGRESS:
				{
					if(e is ProgressEvent){
						this.dispatchEvent(new TraceableEvent(TraceableEvent.PROGRESS,"FileSave","selectSave",ProgressEvent(e).bytesLoaded,ProgressEvent(e).bytesTotal));
					}
					//直接跳出，不删除事件
					return;
				}
				case Event.CANCEL:
				{
					//啥也不干
					break;
				}
				case Event.COMPLETE:
				{
					this.dispatchEvent(new TraceableEvent(TraceableEvent.COMPLETE,"FileSave","selectSave"));
					break;
				}
			}
			file.removeEventListener(Event.COMPLETE,_fileSaveHandler);
			file.removeEventListener(Event.CANCEL,_fileSaveHandler);
			file.removeEventListener(ProgressEvent.PROGRESS,_fileSaveHandler);
			file.removeEventListener(Event.OPEN,_fileSaveHandler);
		}
	}
}